home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 1 / src / pager.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-07-26  |  7.8 KB  |  402 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.pager.c - version 1.0.3 */
  3.  
  4. /* This file contains the command routine dowhatis() and a pager. */
  5. /* Also readmail() and doshell(), and generally the things that
  6.    contact the outside world. */
  7.  
  8. #include    <stdio.h>
  9. #include    <signal.h>
  10. #include "hack.h"
  11. extern int CO, LI;    /* usually COLNO and ROWNO+2 */
  12. extern char *CD;
  13. extern char quitchars[];
  14. extern char *getenv(), *getlogin();
  15. int done1();
  16.  
  17. dowhatis()
  18. {
  19.     FILE *fp;
  20.     char bufr[BUFSZ+6];
  21.     register char *buf = &bufr[6], *ep, q;
  22.     extern char readchar();
  23.  
  24.     if(!(fp = fopen(DATAFILE, "r")))
  25.         pline("Cannot open data file!");
  26.     else {
  27.         pline("Specify what? ");
  28.         q = readchar();
  29.         if(q != '\t')
  30.         while(fgets(buf,BUFSZ,fp))
  31.             if(*buf == q) {
  32.             ep = index(buf, '\n');
  33.             if(ep) *ep = 0;
  34.             /* else: bad data file */
  35.             /* Expand tab 'by hand' */
  36.             if(buf[1] == '\t'){
  37.                 buf = bufr;
  38.                 buf[0] = q;
  39.                 (void) strncpy(buf+1, "       ", 7);
  40.             }
  41.             pline(buf);
  42.             if(ep[-1] == ';') {
  43.                 pline("More info? ");
  44.                 if(readchar() == 'y') {
  45.                     page_more(fp,1); /* does fclose() */
  46.                     return(0);
  47.                 }
  48.             }
  49.             (void) fclose(fp);     /* kopper@psuvax1 */
  50.             return(0);
  51.             }
  52.         pline("I've never heard of such things.");
  53.         (void) fclose(fp);
  54.     }
  55.     return(0);
  56. }
  57.  
  58. /* make the paging of a file interruptible */
  59. static int got_intrup;
  60.  
  61. intruph(){
  62.     got_intrup++;
  63. }
  64.  
  65. /* simple pager, also used from dohelp() */
  66. page_more(fp,strip)
  67. FILE *fp;
  68. int strip;    /* nr of chars to be stripped from each line (0 or 1) */
  69. {
  70.     register char *bufr, *ep;
  71.     int (*prevsig)() = signal(SIGINT, intruph);
  72.  
  73.     set_pager(0);
  74.     bufr = (char *) alloc((unsigned) CO);
  75.     bufr[CO-1] = 0;
  76.     while(fgets(bufr,CO-1,fp) && (!strip || *bufr == '\t') && !got_intrup){
  77.         ep = index(bufr, '\n');
  78.         if(ep)
  79.             *ep = 0;
  80.         if(page_line(bufr+strip)) {
  81.             set_pager(2);
  82.             goto ret;
  83.         }
  84.     }
  85.     set_pager(1);
  86. ret:
  87.     free(bufr);
  88.     (void) fclose(fp);
  89.     (void) signal(SIGINT, prevsig);
  90.     got_intrup = 0;
  91. }
  92.  
  93. static boolean whole_screen = TRUE;
  94. #define    PAGMIN    12    /* minimum # of lines for page below level map */
  95.  
  96. set_whole_screen() {    /* called in termcap as soon as LI is known */
  97.     whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
  98. }
  99.  
  100. #ifdef NEWS
  101. readnews() {
  102.     register int ret;
  103.  
  104.     whole_screen = TRUE;    /* force a docrt(), our first */
  105.     ret = page_file(NEWS, TRUE);
  106.     set_whole_screen();
  107.     return(ret);        /* report whether we did docrt() */
  108. }
  109. #endif NEWS
  110.  
  111. set_pager(mode)
  112. register int mode;    /* 0: open  1: wait+close  2: close */
  113. {
  114.     static boolean so;
  115.     if(mode == 0) {
  116.         if(!whole_screen) {
  117.             /* clear topline */
  118.             clrlin();
  119.             /* use part of screen below level map */
  120.             curs(1, ROWNO+4);
  121.         } else {
  122.             cls();
  123.         }
  124.         so = flags.standout;
  125.         flags.standout = 1;
  126.     } else {
  127.         if(mode == 1) {
  128.             curs(1, LI);
  129.             more();
  130.         }
  131.         flags.standout = so;
  132.         if(whole_screen)
  133.             docrt();
  134.         else {
  135.             curs(1, ROWNO+4);
  136.             cl_eos();
  137.         }
  138.     }
  139. }
  140.  
  141. page_line(s)        /* returns 1 if we should quit */
  142. register char *s;
  143. {
  144.     extern char morc;
  145.  
  146.     if(cury == LI-1) {
  147.         if(!*s)
  148.             return(0);    /* suppress blank lines at top */
  149.         putchar('\n');
  150.         cury++;
  151.         cmore("q\033");
  152.         if(morc) {
  153.             morc = 0;
  154.             return(1);
  155.         }
  156.         if(whole_screen)
  157.             cls();
  158.         else {
  159.             curs(1, ROWNO+4);
  160.             cl_eos();
  161.         }
  162.     }
  163.     puts(s);
  164.     cury++;
  165.     return(0);
  166. }
  167.  
  168. /*
  169.  * Flexible pager: feed it with a number of lines and it will decide
  170.  * whether these should be fed to the pager above, or displayed in a
  171.  * corner.
  172.  * Call:
  173.  *    cornline(0, title or 0)    : initialize
  174.  *    cornline(1, text)    : add text to the chain of texts
  175.  *    cornline(2, morcs)    : output everything and cleanup
  176.  *    cornline(3, 0)        : cleanup
  177.  */
  178.  
  179. cornline(mode, text)
  180. int mode;
  181. char *text;
  182. {
  183.     static struct line {
  184.         struct line *next_line;
  185.         char *line_text;
  186.     } *texthead, *texttail;
  187.     static int maxlen;
  188.     static int linect;
  189.     register struct line *tl;
  190.  
  191.     if(mode == 0) {
  192.         texthead = 0;
  193.         maxlen = 0;
  194.         linect = 0;
  195.         if(text) {
  196.             cornline(1, text);    /* title */
  197.             cornline(1, "");    /* blank line */
  198.         }
  199.         return;
  200.     }
  201.  
  202.     if(mode == 1) {
  203.         register int len;
  204.  
  205.         if(!text) return;    /* superfluous, just to be sure */
  206.         linect++;
  207.         len = strlen(text);
  208.         if(len > maxlen)
  209.         maxlen = len;
  210.         tl = (struct line *)
  211.         alloc((unsigned)(len + sizeof(struct line) + 1));
  212.         tl->next_line = 0;
  213.         tl->line_text = (char *)(tl + 1);
  214.         (void) strcpy(tl->line_text, text);
  215.         if(!texthead)
  216.         texthead = tl;
  217.         else
  218.         texttail->next_line = tl;
  219.         texttail = tl;
  220.         return;
  221.     }
  222.  
  223.     /* --- now we really do it --- */
  224.     if(mode == 2 && linect == 1)                /* topline only */
  225.         pline(texthead->line_text);
  226.     else
  227.     if(mode == 2) {
  228.         register int curline, lth;
  229.  
  230.         if(flags.toplin == 1) more();    /* ab@unido */
  231.         remember_topl();
  232.  
  233.         lth = CO - maxlen - 2;           /* Use full screen width */
  234.         if (linect < LI && lth >= 10) {             /* in a corner */
  235.         home ();
  236.         cl_end ();
  237.         flags.toplin = 0;
  238.         curline = 1;
  239.         for (tl = texthead; tl; tl = tl->next_line) {
  240.             curs (lth, curline);
  241.             if(curline > 1)
  242.             cl_end ();
  243.             putsym(' ');
  244.             putstr (tl->line_text);
  245.             curline++;
  246.         }
  247.         curs (lth, curline);
  248.         cl_end ();
  249.         cmore (text);
  250.         home ();
  251.         cl_end ();
  252.         docorner (lth, curline-1);
  253.         } else {                    /* feed to pager */
  254.         set_pager(0);
  255.         for (tl = texthead; tl; tl = tl->next_line) {
  256.             if (page_line (tl->line_text)) {
  257.             set_pager(2);
  258.             goto cleanup;
  259.             }
  260.         }
  261.         if(text) {
  262.             cgetret(text);
  263.             set_pager(2);
  264.         } else
  265.             set_pager(1);
  266.         }
  267.     }
  268.  
  269. cleanup:
  270.     while(tl = texthead) {
  271.         texthead = tl->next_line;
  272.         free((char *) tl);
  273.     }
  274. }
  275.  
  276. dohelp()
  277. {
  278.     char c;
  279.  
  280.     pline ("Long or short help? ");
  281.     while (((c = readchar ()) != 'l') && (c != 's') && !index(quitchars,c))
  282.         bell ();
  283.     if (!index(quitchars, c))
  284.         (void) page_file((c == 'l') ? HELP : SHELP, FALSE);
  285.     return(0);
  286. }
  287.  
  288. page_file(fnam, silent)    /* return: 0 - cannot open fnam; 1 - otherwise */
  289. register char *fnam;
  290. boolean silent;
  291. {
  292. #ifdef DEF_PAGER            /* this implies that UNIX is defined */
  293.       {
  294.     /* use external pager; this may give security problems */
  295.  
  296.     register int fd = open(fnam, 0);
  297.  
  298.     if(fd < 0) {
  299.         if(!silent) pline("Cannot open %s.", fnam);
  300.         return(0);
  301.     }
  302.     if(child(1)){
  303.         extern char *catmore;
  304.  
  305.         /* Now that child() does a setuid(getuid()) and a chdir(),
  306.            we may not be able to open file fnam anymore, so make
  307.            it stdin. */
  308.         (void) close(0);
  309.         if(dup(fd)) {
  310.             if(!silent) printf("Cannot open %s as stdin.\n", fnam);
  311.         } else {
  312.             execl(catmore, "page", (char *) 0);
  313.             if(!silent) printf("Cannot exec %s.\n", catmore);
  314.         }
  315.         exit(1);
  316.     }
  317.     (void) close(fd);
  318.       }
  319. #else DEF_PAGER
  320.       {
  321.     FILE *f;            /* free after Robert Viduya */
  322.  
  323.     if ((f = fopen (fnam, "r")) == (FILE *) 0) {
  324.         if(!silent) {
  325.             home(); perror (fnam); flags.toplin = 1;
  326.             pline ("Cannot open %s.", fnam);
  327.         }
  328.         return(0);
  329.     }
  330.     page_more(f, 0);
  331.       }
  332. #endif DEF_PAGER
  333.  
  334.     return(1);
  335. }
  336.  
  337. #ifdef UNIX
  338. #ifdef SHELL
  339. dosh(){
  340. register char *str;
  341.     if(child(0)) {
  342.         if(str = getenv("SHELL"))
  343.             execl(str, str, (char *) 0);
  344.         else
  345.             execl("/bin/sh", "sh", (char *) 0);
  346.         pline("sh: cannot execute.");
  347.         exit(1);
  348.     }
  349.     return(0);
  350. }
  351. #endif SHELL
  352.  
  353. #ifdef NOWAITINCLUDE
  354. union wait {        /* used only for the cast  (union wait *) 0  */
  355.     int w_status;
  356.     struct {
  357.         unsigned short w_Termsig:7;
  358.         unsigned short w_Coredump:1;
  359.         unsigned short w_Retcode:8;
  360.     } w_T;
  361. };
  362.  
  363. #else
  364.  
  365. #ifdef BSD
  366. #include    <sys/wait.h>
  367. #else
  368. #include    <wait.h>
  369. #endif BSD
  370. #endif NOWAITINCLUDE
  371.  
  372. child(wt) {
  373. register int f = fork();
  374.     if(f == 0){        /* child */
  375.         settty((char *) 0);        /* also calls end_screen() */
  376.         (void) setuid(getuid());
  377.         (void) setgid(getgid());
  378. #ifdef CHDIR
  379.         (void) chdir(getenv("HOME"));
  380. #endif CHDIR
  381.         return(1);
  382.     }
  383.     if(f == -1) {    /* cannot fork */
  384.         pline("Fork failed. Try again.");
  385.         return(0);
  386.     }
  387.     /* fork succeeded; wait for child to exit */
  388.     (void) signal(SIGINT,SIG_IGN);
  389.     (void) signal(SIGQUIT,SIG_IGN);
  390.     (void) wait((union wait *) 0);
  391.     gettty();
  392.     setftty();
  393.     (void) signal(SIGINT,done1);
  394. #ifdef WIZARD
  395.     if(wizard) (void) signal(SIGQUIT,SIG_DFL);
  396. #endif WIZARD
  397.     if(wt) getret();
  398.     docrt();
  399.     return(0);
  400. }
  401. #endif UNIX
  402.